/*************************************************************************
    > File Name    : LRUCache.cc
    > Author       : LiuLei
    > Mail         : 2261459486@qq.com 
    > Created Time : 2022年11月30日 星期三 14时12分05秒
 ************************************************************************/

#include "../../include/server/LRUCache.h"
#include <iostream>
#include <fstream>
#include <sstream>
using std::make_pair;
using std::cout;
using std::endl;
using std::ifstream;
using std::istringstream;
using std::ofstream;

LRUCache::LRUCache(int capacity)
: _capacity(capacity)
{

}

LRUCache::~LRUCache()
{

}

void LRUCache::addElement(const string &key, const ElemType &value)
{
    // 如果LRU缓存中没有这个要添加的数据
    if(!_hashMap.count(key))
    {
        // 缓存已经满了，此时则需要淘汰最久没有使用过的数据
        if(_pendingUpdateList.size() == _capacity)
        {
            _hashMap.erase(_resultList.back().first);
            _pendingUpdateList.pop_back();
        }
    }
    else
    {
        _pendingUpdateList.erase(_hashMap.at(key));
    }

    // 将元素加入链表头部
    _pendingUpdateList.push_front(make_pair(key, value));
    _hashMap[key] = _pendingUpdateList.begin();
}

void LRUCache::readFromFile(const string &filename)
{
    ifstream ifs;
    ifs.open(filename, std::ios::in);
    if(!ifs.good())
    {
        cout << "Open " << filename << " error in LRUCache::readFromFile()!" << endl;
        return ;
    }

    string cacheData;
    while(getline(ifs, cacheData))
    {
        string key;
        ElemType value;
        istringstream iss(cacheData);
        if(iss)
        {
            iss >> key;
        }
        if(iss)
        {
            iss >> value;
        }
        _resultList.push_back(make_pair(key, value));

        cacheData.clear();
    }
    ifs.close();
}

void LRUCache::writeToFile(const string &filename)
{
    ofstream ofs;
    ofs.open(filename, std::ios::out);
    if(!ofs.good())
    {
        cout << "Open " << filename << " error in LRUCache::writeToFile()" << endl;
        return ;
    }

    for(list<pair<string, ElemType>>::iterator it = _pendingUpdateList.begin();
        it != _pendingUpdateList.end();
        ++it)
    {
        ofs << (*it).first << "  " << (*it).second << endl;
    }
}
